#include "web/PageLib.hh"
#include "web/tinyxml2.h"

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <memory>
#include <regex>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

using namespace tinyxml2;
using std::cout;
using std::string;
using std::to_string;
using std::vector;
using std::ifstream;
using std::ofstream;
using std::unique_ptr;
using std::regex;


std::size_t length(const std::string &str);
PageLib::PageLib(){

}
void PageLib::create(){
    auto& confMap = Configuration::createConfig()->getConfigMap();

    vector<string> dirs = confMap["yuliao"];
    XMLDocument doc;
    for(auto& elem : dirs){
        cout << elem << "\n";
        // tiny 处理xml网页
        cleanWebPage(elem, doc);
    }
    doc.SaveFile(confMap["ripepage"][0].c_str());
}
void PageLib::store(){
    auto& confMap = Configuration::createConfig()->getConfigMap();
    string file_name = confMap["offset"][0];
    ofstream ofs(file_name);
    cout << "store offset to \n";
    for(auto& elem : _offsetLib){
        ofs << elem.first << " ";
        ofs << elem.second.first << " ";
        ofs << elem.second.second << "\n";
    }
    cout << "store offset to \n";
}

void PageLib::cleanWebPage(string& webPage, XMLDocument& doc){
    auto& confMap = Configuration::createConfig()->getConfigMap();
    static int count = 1;

    XMLDocument doc1;
    doc1.LoadFile(webPage.c_str());
    // NOTE: 检错

    XMLElement *root = doc1.RootElement()->FirstChildElement()->FirstChildElement("item");

    ifstream ifs;
    regex reg("<.*?>");
    for (XMLElement *p = root; p != nullptr; p = p->NextSiblingElement())
    {
        XMLElement *xml_title = p->FirstChildElement("title");
        XMLElement *xml_url = p->FirstChildElement("link");
        XMLElement *xml_content = p->FirstChildElement("description");
        if (xml_title == nullptr 
            || xml_url == nullptr 
            || xml_content == nullptr )
            {continue;}

        string title = xml_title->GetText();
        string url = xml_url->GetText();
        string content = regex_replace(xml_content->GetText(), reg, "");
        if(length(content) == content.size()){ continue;}
        
        // doc 根节点
        XMLNode *Root = doc.NewElement("doc");
        doc.InsertEndChild(Root);

        // 添加 docid
        XMLElement *_docid = doc.NewElement("docid");
        Root->InsertEndChild(_docid);

        XMLText *text_docid = doc.NewText(to_string(count).c_str());
        _docid->InsertEndChild(text_docid);

        // 添加 title
        XMLElement *_title = doc.NewElement("title");
        Root->InsertEndChild(_title);

        XMLText *text_title = doc.NewText(title.c_str());
        _title->InsertEndChild(text_title);

        // 添加 url
        XMLElement *_url = doc.NewElement("url");
        Root->InsertEndChild(_url);

        XMLText *text_url = doc.NewText(url.c_str());
        _url->InsertEndChild(text_url);

        // 添加 content
        XMLElement *_content = doc.NewElement("content");
        Root->InsertEndChild(_content);

        XMLText *text_content = doc.NewText(content.c_str());
        _content->InsertEndChild(text_content);
        /*************************************************************/
        ifs.open(confMap["ripepage"][0], std::ios::ate);
        size_t old_size = ifs.tellg();
        ifs.close();

        doc.SaveFile(confMap["ripepage"][0].c_str());
        
        ifs.open(confMap["ripepage"][0], std::ios::ate);
        size_t new_size = ifs.tellg();
        ifs.close();

        _offsetLib.insert({count, {old_size, new_size - old_size -1}});
        count++;
    }

}



inline size_t nBytesCode(const char ch)
{
	if(ch & (1 << 7))
	{
		int nBytes = 1;
		for(int idx = 0; idx != 6; ++idx)
		{
			if(ch & (1 << (6 - idx)))
			{
				++nBytes;	
			}
			else
				break;
		}
		return nBytes;
	}
	return 1;
}  


inline std::size_t length(const std::string &str)
{
	std::size_t ilen = 0;
	for(std::size_t idx = 0; idx != str.size(); ++idx)
	{
		int nBytes = nBytesCode(str[idx]);
		idx += (nBytes - 1);
		++ilen;
	}
	return ilen;
}